import base64
import hashlib
import hmac
import json
import ssl
import threading
import time
from datetime import datetime
from time import mktime
from urllib.parse import urlencode
import websocket
from wsgiref.handlers import format_date_time


class IflytekClient:
    STATUS_FIRST_FRAME = 0
    STATUS_CONTINUE_FRAME = 1
    STATUS_LAST_FRAME = 2

    def __init__(self, appid, apikey, apisecret, on_result_callback):

        print(appid)
        print(apikey)
        print(apisecret)
        self.appid = appid
        self.apikey = apikey
        self.apisecret = apisecret
        self.on_result_callback = on_result_callback
        self.ws = None
        self.connected = threading.Event()

    def create_url(self):
        url = "wss://ws-api.xfyun.cn/v2/iat"
        now = datetime.utcnow()
        date = format_date_time(mktime(now.timetuple()))
        signature_origin = f"host: ws-api.xfyun.cn\ndate: {date}\nGET /v2/iat HTTP/1.1"
        signature_sha = hmac.new(
            self.apisecret.encode("utf-8"), signature_origin.encode("utf-8"), digestmod=hashlib.sha256
        ).digest()
        signature_base64 = base64.b64encode(signature_sha).decode("utf-8")
        authorization_origin = (
            f'api_key="{self.apikey}", algorithm="hmac-sha256", headers="host date request-line", signature="{signature_base64}"'
        )
        authorization = base64.b64encode(authorization_origin.encode("utf-8")).decode("utf-8")
        params = urlencode({
            "authorization": authorization,
            "date": date,
            "host": "ws-api.xfyun.cn"
        })
        return f"{url}?{params}"

    def connect(self):
        ws_url = self.create_url()
        print(ws_url)

    # def on_message(ws, message):
    #     try:
    #         resp = json.loads(message)
    #         code = resp.get("code")
    #         sid = resp.get("sid", "")
    #         if code != 0:
    #             errMsg = resp.get("message", "未知错误")
    #             print(f"讯飞接口返回错误,sid: {sid},code: {code},message: {errMsg}")
    #         else:
    #             data = resp["data"]["result"]["ws"]
    #             result = ""
    #             for i in data:
    #                 for w in i["cw"]:
    #                     result += w["w"]
    #             print(f"讯飞识别成功,sid: {sid}，结果: {result}")
    #     except Exception as e:
    #         print("解析讯飞消息出错:", e)

        def on_message(ws, message):
            
            try:
                data = json.loads(message)
                print(data)
                if data.get("code") != 0:
                    print("Error:", data.get("message"))
                else:
                    result = ""
                    for i in data["data"]["result"]["ws"]:
                        for w in i["cw"]:
                            result += w["w"]
                            print(result)
                    if self.on_result_callback:
                        self.on_result_callback(result)
            except Exception as e:
                print("Message parse error:", e)

        def on_error(ws, error):
            print("WebSocket error:", error)

        def on_close(ws, *args):
            print("WebSocket closed")

        def on_open(ws):
            self.connected.set()

        self.ws = websocket.WebSocketApp(
            ws_url,
            on_message=on_message,
            on_error=on_error,
            on_close=on_close,
            on_open=on_open,
        )

        threading.Thread(target=self.ws.run_forever, kwargs={"sslopt": {"cert_reqs": ssl.CERT_NONE}}, daemon=True).start()
        self.connected.wait()

    def send_audio(self, chunk: bytes, is_last=False):
        if not self.ws:
            return

        if is_last:
            status = self.STATUS_LAST_FRAME
            # print("STATUS_LAST_FRAME")
        elif not hasattr(self, "_sent_first"):
            status = self.STATUS_FIRST_FRAME
            # print("STATUS_FIRST_FRAME")
        else:
            status = self.STATUS_CONTINUE_FRAME
            # print("STATUS_CONTINUE_FRAME")

        data = {
            "data": {
                "status": status,
                "format": "audio/L16;rate=8000",
                "audio": base64.b64encode(chunk).decode("utf-8"),
                "encoding": "raw"
            }
        }

        if status == self.STATUS_FIRST_FRAME:
            self._sent_first = True
            data["common"] = {"app_id": self.appid}
            data["business"] = {
                "domain": "iat",
                "language": "zh_cn",
                "accent": "mandarin",
                "vinfo": 1,
                "vad_eos": 10000
            }
        #print(data)
        self.ws.send(json.dumps(data))

    def close(self):
        self.send_audio(b"", is_last=True)
        time.sleep(1)
        if self.ws:
            self.ws.close()
